package com.example.project.projectspringcloud.controller.front.user;

import com.example.project.projectspringcloud.common.Constants;
import com.example.project.projectspringcloud.common.OperationException;
import com.example.project.projectspringcloud.controller.BaseController;
import com.example.project.projectspringcloud.entity.RespBody;
import com.example.project.projectspringcloud.entity.sys.Dictionary;
import com.example.project.projectspringcloud.entity.user.User;
import com.example.project.projectspringcloud.entity.user.UserProfile;
import com.example.project.projectspringcloud.entity.user.pojo.UserPojo;
import com.example.project.projectspringcloud.service.sys.SysDictionaryService;
import com.example.project.projectspringcloud.service.user.UserProfileService;
import com.example.project.projectspringcloud.service.user.UserService;
import com.example.project.projectspringcloud.utils.RedisUtil;
import com.example.project.projectspringcloud.utils.StringUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.util.List;
import java.util.Optional;

@Api(tags = "个人中心")
@Controller
@RequestMapping(value = "/personal")
public class PersonalController extends BaseController {

    private final Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    private UserService userService;

    @Autowired
    private SysDictionaryService sysDictionaryService;

    @Autowired
    private UserProfileService userProfileService;

    @Autowired
    private RedisUtil redisUtil;

    @ApiOperation(value = "个人中心", notes = "返回个人中心")
    @GetMapping(value = {"", "/"})
    public String info(@RequestParam(value = "type", required = false) Integer type, Model model) {
        Integer userId = super.getCurrentUser().getId();
        User currentUser = userService.getWithPrivate(new User(userId));
        model.addAttribute("user", currentUser);

        List<Dictionary> dictionaryList = sysDictionaryService.list(new Dictionary("expect"), null);
        model.addAttribute("dictionaryList", dictionaryList);
        if (type != null) {
            return isMobile() ? "m/content/personal/personal-info" : "content/personal/user-info-edit";
        }
        return isMobile() ? "m/content/personal/personal" : "content/personal/user-info";
    }

    @ApiOperation(value = "表单保存用户信息", notes = "根据ID判断是否存在, 执行是否更新/插入")
    @PostMapping(value = "/save")
    public String save(@Validated User user, BindingResult bindingResult, Model model) {
        try {
            if (bindingResult.getErrorCount() > 0) {
                model.addAttribute("user", user);
                model.addAttribute("error", super.translateI18N(bindingResult));
                return "content/personal/user-info-edit";
            }

            user.setId(super.getCurrentUser().getId());
            boolean result = userService.save(user);
            if (!result) {
                model.addAttribute("user", user);
                model.addAttribute("error", Constants.Message.SAVE_FAILED);
                return "content/personal/user-info-edit";
            }
        } catch (OperationException e) {
            logger.error(Constants.Message.SAVE_FAILED, e);
            model.addAttribute("user", user);
            model.addAttribute("error", super.translateI18N(Constants.SystemMessage.SYSTEM_ERROR));
            return "content/personal/user-info-edit";
        }

        return "redirect:/personal";
    }

    @ApiOperation(value = "按类型保存用户信息", notes = "按类型保存用户信息")
    @PostMapping(value = "/save/{type}")
    @ResponseBody
    public RespBody save(@PathVariable("type") String type, @RequestParam(value = "param", required = false) String param) {
        User user = userService.getWithPrivate(new User(super.getCurrentUser().getId()));

        switch (type) {
            case "name":
                if (StringUtils.isNotBlank(param)) {
                    return RespBody.error("姓名不能为空!");
                }
                user.setName(param);
                break;
            case "nickname":
                if (StringUtils.isNotBlank(param)) {
                    return RespBody.error("昵称不能为空!");
                }
                user.setNickname(param);
                break;
            case "gender":
                if (StringUtils.isNotBlank(param)) {
                    return RespBody.error("性别不能为空!");
                }
                user.setGender(Integer.parseInt(param));
                break;
            case "expect":
                user.setExpect(Integer.parseInt(param));
                break;
            case "email":
                user.setEmail(param);
                break;
            case "wechat":
                user.setWechat(param);
                break;
            case "qq":
                user.setQq(param);
                break;
            case "requirementText":
                user.setRequirementText(param);
                break;
            default:
                return RespBody.ok(true);
        }
        try {
            userService.saveAbsolute(user);
        } catch (Exception e) {
            logger.error(super.translateI18N(Constants.Message.SAVE_FAILED), e);
            return RespBody.error(super.translateI18N(Constants.Message.SAVE_FAILED));
        }
        return RespBody.ok(true);
    }

    @ApiOperation(value = "安全中心", notes = "返回安全中心")
    @GetMapping(value = "/safe")
    public String safe(Model model) {
        Integer userId = super.getCurrentUser().getId();
        User currentUser = userService.getWithPrivate(new User(userId));
        model.addAttribute("currentUser", currentUser);

        UserProfile entity = new UserProfile();
        entity.setUserId(userId);
        entity.setType(Constants.ThirdPartType.QQ.toString());
        model.addAttribute(Constants.ThirdPartType.QQ.toString(), userProfileService.get(entity));

        entity.setType(Constants.ThirdPartType.SINAWEIBO.toString());
        model.addAttribute(Constants.ThirdPartType.SINAWEIBO.toString(), userProfileService.get(entity));

        entity.setType(Constants.ThirdPartType.WECHAT.toString());
        model.addAttribute(Constants.ThirdPartType.WECHAT.toString(), userProfileService.get(entity));
        return "content/personal/user-security";
    }

    @ApiOperation(value = "返回页面", notes = "返回页面")
    @GetMapping(value = "/safe/{type}")
    public String link(@PathVariable("type") String type, Model model) {
        model.addAttribute("currentUser", super.getCurrentUser());
        switch (type) {
            case "password":
                return isMobile() ? "m/content/personal/retrieve-password" : "content/personal/user-security-modify-password";
            case "mobile":
                return isMobile() ? "m/content/personal/retrieve-phone" : "content/personal/user-security-modify-phone-step-one";
            default:
                return "redirect:/404";
        }
    }

    @ApiOperation(value = "手机号修改第一步提交", notes = "手机号修改第一步提交, 返回第二步")
    @PostMapping(value = "/safe/modify-mobile/{step}")
    public String modifyMobile(@ApiParam(value = "手机号修改操作步骤") @PathVariable("step") Integer step,
                               @RequestParam(value = "validateCode", required = false) String validateCode,
                               @RequestParam(value = "smsCode", required = false) String smsCode,
                               @RequestParam(value = "mobile", required = false) String mobile,
                               HttpServletRequest request, Model model) throws OperationException {
        switch (step) {
            case 1:
                // 校验图形验证码
                /*if (StringUtils.isBlank(sessionValidateCode) || !sessionValidateCode.equals(validateCode)) {
                    model.addAttribute("error", super.translateI18N(Constants.Message.VALIDATE_ERROR));
                    model.addAttribute("currentUser", super.getCurrentUser());
                    return "content/personal/user-security-modify-phone-step-one";
                }*/
                // 校验短信验证码
                if (!redisUtil.hasKey(Constants.SMS_VALIDATE_CODE_OF + super.getCurrentUser().getMobile())
                        || !smsCode.equals(redisUtil.get(Constants.SMS_VALIDATE_CODE_OF + super.getCurrentUser().getMobile()))) {
                    model.addAttribute("error", super.translateI18N(Constants.Tip.SMS_VALIDATE_CODE_DIFFERENT));
                    model.addAttribute("currentUser", super.getCurrentUser());
                    return isMobile() ? "m/content/personal/retrieve-phone" : "content/personal/user-security-modify-phone-step-one";
                }
                redisUtil.del(Constants.SMS_VALIDATE_CODE_OF + super.getCurrentUser().getMobile());
                request.getSession().setAttribute("step", 2);
                return isMobile() ? "m/content/personal/retrieve-phone-2" : "content/personal/user-security-modify-phone-step-two";
            case 2:
                Integer temp = (Integer) request.getSession().getAttribute("step");
                if (temp == null || temp != 2) {
                    throw new OperationException();
                }
                // 校验图形验证码
                /*if (StringUtils.isBlank(sessionValidateCode) || !sessionValidateCode.equals(validateCode)) {
                    model.addAttribute("error", super.translateI18N(Constants.Message.VALIDATE_ERROR));
                    model.addAttribute("mobile", mobile);
                    return "content/personal/user-security-modify-phone-step-two";
                }*/
                if (!redisUtil.hasKey(Constants.SMS_VALIDATE_CODE_OF + mobile)
                        || !smsCode.equals(redisUtil.get(Constants.SMS_VALIDATE_CODE_OF + mobile))) {
                    model.addAttribute("error", super.translateI18N(Constants.Tip.SMS_VALIDATE_CODE_DIFFERENT));
                    model.addAttribute("mobile", mobile);
                    return isMobile() ? "m/content/personal/retrieve-phone-2" : "content/personal/user-security-modify-phone-step-two";
                }
                redisUtil.del(Constants.SMS_VALIDATE_CODE_OF + mobile);

                User entity = new User();
                entity.setMobile(mobile);
                entity = userService.get(entity);
                // 如果新手机号查找到用户, 则不可用
                if (entity != null) {
                    model.addAttribute("error", super.translateI18N(Constants.Tip.ACCOUNT_MOBILE_EXIST));
                    return isMobile() ? "m/content/personal/retrieve-phone-2" : "content/personal/user-security-modify-phone-step-two";
                }
                entity = userService.get(new User(super.getCurrentUser().getId()));
                entity.setMobile(mobile);
                entity.setAccount(mobile);
                userService.save(entity);
                return isMobile() ? "m/content/personal/retrieve-phone-3" : "content/personal/user-security-modify-phone-step-three";
            default:
                return "redirect:/404";
        }
    }

    @ApiOperation(value = "修改密码", notes = "个人中心修改密码")
    @PostMapping(value = "/safe/modify-password")
    public String modifyPassword(@Valid UserPojo user, BindingResult bindingResult, Model model, RedirectAttributes redirectAttributes) {
        // validate account, mobile, password, nickname
        if (bindingResult.getErrorCount() > 0) {
            model.addAttribute("error", super.translateI18N(bindingResult));
            return "content/personal/user-security-modify-password";
        }

        // 再次密码不一致
        if (!user.getPassword().equals(user.getPasswords())) {
            model.addAttribute("error", super.translateI18N(Constants.Tip.THE_TWO_PASSWORD_ARE_DIFFERENT));
            return "content/personal/user-security-modify-password";
        }

        if (!redisUtil.hasKey(Constants.SMS_VALIDATE_CODE_OF + user.getMobile())
                || !user.getValidate().equals(redisUtil.get(Constants.SMS_VALIDATE_CODE_OF + user.getMobile()))) {
            model.addAttribute("error", super.translateI18N(Constants.Tip.SMS_VALIDATE_CODE_DIFFERENT));
            return "content/personal/user-security-modify-password";
        }

        // 根据原始密码查找
        User entity = new User();
        entity.setMobile(super.getCurrentUser().getMobile());
        entity.setPwd(StringUtil.md5(user.getOriginPassword()));
        if (!Optional.ofNullable(userService.getWithPrivate(entity)).isPresent()) {
            model.addAttribute("error", super.translateI18N(Constants.Message.PASSWORD_ERROR));
            return "content/personal/user-security-modify-password";
        }

        redisUtil.del(Constants.SMS_VALIDATE_CODE_OF + user.getMobile());

        try {
            // 找回
            userService.retrieve(user);
        } catch (OperationException e) {
            logger.error("IndexController.retrieve", e);
            model.addAttribute("error", super.translateI18N(Constants.Tip.SMS_VALIDATE_CODE_DIFFERENT));
            return "content/personal/user-security-modify-password";
        }
        return "redirect:/personal/safe";
    }

    @ApiOperation(value = "API修改密码", notes = "个人中心修改密码")
    @PostMapping(value = "/api/safe/modify-password")
    @ResponseBody
    public RespBody modifyPassword(@Valid UserPojo user, BindingResult bindingResult) {
        // validate account, mobile, password, nickname
        if (bindingResult.getErrorCount() > 0) {
            return RespBody.error(super.translateI18N(bindingResult));
        }

        // 再次密码不一致
        if (!user.getPassword().equals(user.getPasswords())) {
            return RespBody.error(super.translateI18N(Constants.Tip.THE_TWO_PASSWORD_ARE_DIFFERENT));
        }

        if (!redisUtil.hasKey(Constants.SMS_VALIDATE_CODE_OF + user.getMobile())
                || !user.getValidate().equals(redisUtil.get(Constants.SMS_VALIDATE_CODE_OF + user.getMobile()))) {
            return RespBody.error(super.translateI18N(Constants.Tip.SMS_VALIDATE_CODE_DIFFERENT));
        }

        // 根据原始密码查找
        User entity = new User();
        entity.setMobile(super.getCurrentUser().getMobile());
        entity.setPwd(StringUtil.md5(user.getOriginPassword()));
        if (!Optional.ofNullable(userService.getWithPrivate(entity)).isPresent()) {
            return RespBody.error(super.translateI18N(Constants.Message.PASSWORD_ERROR));
        }

        redisUtil.del(Constants.SMS_VALIDATE_CODE_OF + user.getMobile());

        try {
            // 找回
            userService.retrieve(user);
        } catch (OperationException e) {
            logger.error("IndexController.retrieve", e);
            return RespBody.error(super.translateI18N(Constants.Tip.SMS_VALIDATE_CODE_DIFFERENT));
        }
        return RespBody.ok(true);
    }
}
